#ifndef __S264_COMM_IMPL_H__
#define __S264_COMM_IMPL_H__


// 类型定义
typedef char i8;
typedef short i16;
typedef int i32;
typedef long i64;

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long u64;

typedef float f32;
typedef double f64;


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define s264_malloc(size) malloc(size)
#define s264_free(ptr) free(ptr)
#define s264_memcpy(dst,src,len) memcpy(dst,src,len)
#define s264_memset(s,c,n) memset(s,c,n)
#define s264_memcmp(s1,s2,n) memcmp(s1,s2,n)

#define s264_print(fmt, ...) fprintf(stdout, "[%s:%s():%d] " fmt "\n", __FILE__, __func__, __LINE__, ##__VA_ARGS__)

typedef struct s264buf_st {
	u8 *data;
	u64 len;
	u64 cap;
}s264buf_t;

#define s264buf_enlarging_multiple (2)
#define s264buf_use_percentage (3.0/4.0)
static i8 s264buf_init(s264buf_t *p,u64 cap)
{
	if (p == NULL)
		return -1;
	p->data = (u8 *) s264_malloc(cap);
	if (p->data == NULL)
		return -2;
	p->len = 0;
	p->cap = cap;
	s264_memset(p->data, 0, p->cap);
	return 0;
}

static void s264buf_deinit(s264buf_t *p)
{
	if (p == NULL)
		return;
	if (p->data != NULL)
		s264_free(p->data);
	s264_memset(p, 0, sizeof(s264buf_t));
}

static i8 s264buf_enlarging(s264buf_t *p)
{
	if (p == NULL || p->data == NULL)
		return -1;
	u64 multiple = s264buf_enlarging_multiple < 2 ? 2 : s264buf_enlarging_multiple;
	u64 new_cap = p->cap * multiple;
	u8 *data = s264_malloc(new_cap);
	if (data == NULL)
		return -2;
	s264_memset(data, 0, new_cap);
	s264_memcpy(data, p->data, p->len);
	s264_free(p->data);
	p->data = data;
	p->cap = new_cap;
	return 0;
}

static i8 s264buf_append(s264buf_t *p, u8 *buf, u64 len)
{
	if (p == NULL || buf == NULL || len <= 0)
		return -1;
	u64 can_use_cap = p->cap * s264buf_use_percentage;
	if (len + p->len >= can_use_cap)
	{
		if (s264buf_enlarging(p)) // 扩容失败
			return -2;
	}
	s264_memcpy(p->data+p->len, buf, len);
	p->len += len;
	return 0;
}

static i8 s264buf_clear(s264buf_t *p)
{
	if (p == NULL)
		return -1;
	s264_memset(p->data, 0, p->cap);
	p->len = 0;
	return 0;
}

#endif